René Nyffenegger's collection of things on the web | |
René Nyffenegger on Oracle - Most wanted - Feedback
- Follow @renenyffenegger
|
JavaScript Menu | ||
I have been experimenting with JavaScript in order to have a JavaScript Menu. The goal was not a cross browser Menu, but
a Menu that I can use to study the nessessary things.
A lot was inspired by http://www.cfoster.net/tmenu.
The JavaScript functions (basic_menu.js)var root_elem; var g_menu_item_border_size = 1; var g_menu_item_height_wo_border = 15; var menu_bar_counter = 0; var id_counter = 0; var all_objs = {}; function getBrowserWidth() {return root_elem.clientWidth; } function getBrowserHeight(){return root_elem.clientHeight; } function getScrollY() {return root_elem.scrollTop; } function getScrollX() {return root_elem.scrollLeft; } function getX(obj) {return obj.offsetLeft + layout.getLeft(obj); } function getY(obj) {return layout.getTop(obj) + layout.getHeight(obj);} function Menu(label) { id_counter++; this.id = id_counter; this.id_label = "label_id_" + id_counter; all_objs[id_counter] = this; this.menu_items = []; this.ids_of_items = []; this.menu_item = new MenuItem(label, this.id, this.id_label, this); this.is_menu = true; } function MenuItem(label, id_menu, id, menu) { this.label = label; this.id_menu = id_menu; this.id = id; this.menu = menu; all_objs[id] = this; } function MenuAction(label, href) { id_counter++; this.id_label = "label_id_" + id_counter; all_objs[id_counter] = this; this.label = label; this.href = href; this.is_menu = false; } function test_id(obj, id) { // Tests, if obj's id IS id // The parameter id is a string if (obj == null) return false; if (typeof(obj ) == "undefined") return false; if (typeof(obj.id) == "undefined") return false; if (obj.id==id) return true; return false; } Menu.prototype.close = function() { document.getElementById(this.id).style.visibility = "hidden"; var menu_label = document.getElementById(this.id_label); menu_label.style.zIndex = 0; } Menu.prototype.open = function() { var menu_label = document.getElementById(this.id_label); var menu_div = document.getElementById(this.id); if (! this.width_calculated) { var max_width = 0; for (var i=0;i<this.ids_of_items.length;i++) { var m = document.getElementById(this.ids_of_items[i]) if (m.offsetWidth > max_width) max_width = m.offsetWidth; } menu_div.style.posWidth = max_width+1; for (var i=0;i<this.ids_of_items.length;i++) { var m = document.getElementById(this.ids_of_items[i]) m.style.posWidth = max_width-2; } this.width_calculated = true; menu_div.style.height=i*(g_menu_item_height_wo_border+2*g_menu_item_border_size)+2; menu_div.style.width =max_width; } menu_div.style.left = menu_label.clientWidth -20; menu_label.style.zIndex = 1; menu_div.style.visibility = "visible"; } Menu.prototype.mouse_leave = function() { for (var i=0;i<this.menu_items.length;i++) { if (this.menu_items[i].is_menu) this.menu_items[i].close(); } if (event.toElement == null) return; // todo: "label_id_" if (! test_id(event.toElement, "label_id_" + this.id) && ! test_id(event.toElement.offsetParent, "label_id_" + this.id)) { this.close(); } } MenuItem.prototype.mouse_leave = function() { var to_elem = event.toElement; if (to_elem == null) { this.menu.close(); return; } if (! test_id(to_elem, this.id_menu) && ! test_id(to_elem.offsetParent, this.id_menu)) { this.menu.close(); return; } } MenuItem.prototype.mouse_enter = function() { this.menu.open(); } MenuAction.prototype.a = function(y, x) { var ret=""; ret += "<a id='" + this.id_label + "' "; ret += "href='"+this.href+"' "; ret += " style='top:" + y + ";left:" + x + "' "; ret += "class='MenuItemCl'>"; ret += this.label; ret += "</a>"; return ret; } MenuItem.prototype.a = function(y, x) { var ret = ""; ret += "<a id='" + this.id + "' "; ret += "onMouseEnter='javascript:all_objs[\""+this.id+"\"].mouse_enter();'"; ret += " onMouseLeave='javascript:all_objs[\""+this.id+"\"].mouse_leave();'"; ret += " style='top:" + y + ";left:" + x + "' "; ret += " class='MenuItemCl' href='javascript:void(0)'>"; ret += this.label; ret += this.menu.GetMenuDivTodo(); ret += "</a>"; return ret; } Menu.prototype.a = function(y, x) { var ret=""; ret += this.menu_item.a(y, x); return ret; }; Menu.prototype.GetMenuDivTodo = function() { var ret = "<div id='"+this.id+"' class='MenuCl' " ret += "onMouseLeave='javascript:all_objs["+this.id+"].mouse_leave();'>"; var is_first = 1; for (var i=0;i<this.menu_items.length;i++) { ret += this.menu_items[i].a(i*(g_menu_item_height_wo_border + 2*g_menu_item_border_size), 0); is_first = 0; } ret += "</div>"; return ret; } Menu.prototype.add = function(o) { this.menu_items[this.menu_items.length] = o; this.ids_of_items[this.ids_of_items.length] = o.id_label; }; MenuAction.prototype.hide = function() { document.getElementById(this.id).style.visibility = "hidden"; } MenuAction.prototype.show = function() { document.getElementById(this.id).style.visibility = "visible"; } function MenuBar(x,y) { // todo: x und y werden nicht beruecksichtigt this.id = menu_bar_counter++; this.x = x; this.y = y; this.isAbsolute = false; this.contained_objs = []; this.img_loaded = false; this.width_calculated = false; } MenuBar.prototype.add = function(obj) { this.contained_objs[this.contained_objs.length] = obj; }; MenuBar.prototype.toString = function() { display = "position:absolute;left:"+this.x+"px;top:"+this.y+"px;"; var ret = "<span id='"+this.id+"' class='MenuBarCl' "+((this.isAbsolute) ? " style='margin:0px;padding:0px;"+display+"'":""); ret +=">"; for (var i=0;i<this.contained_objs.length;i++) { ret += this.contained_objs[i].a(0, i*120); } ret += "</span>"; return ret; }; function basic_menu_load() { var ieBox = document.compatMode == null || document.compatMode != "CSS1Compat"; if (ieBox) root_elem = document.body; else root_elem = document.documentElement; } The CSS file (basic_menu_1.css).MenuBarCl { position : absolute; } .MenuCl { position : absolute; background-color: #BED5DC; visibility : hidden; border : 1px solid #000000; width : 400; } .MenuBarCl .MenuItemCl { width : 120; } .MenuItemCl { position : absolute; border : 1px solid #ECECEC; background-color: #ECECEC; padding : 1px 5px 0px 7px; text-decoration : none; font-family : Verdana,Arial,Sans-Serif; font-size : 12px; text-align : left; color : #000000; margin : 0px; height : 15px; } .MenuItemCl:hover { background-color: #C0C0E0; color : #0000FF; border : 1px solid #000000; height : 15px; text-decoration : none; } .MenuSeparatorCl { font-size : 0px; background-color: #BED5DC; height : 1px; margin : 1px; border-top : 1px solid #FFFFFF; border-bottom : 1px solid #FFFFFF; } .test_width { visibility : hidden; } A HTML file using basic_menu.js<html> <head> <title>Basic Javascript Menu</title> <link rel ='stylesheet' type ='text/css' href='basic_menu_1.css'> <script type='text/javascript' language='javascript' src ='basic_menu.js'> </script> </head> <script language=javascript> var menu_bar = new MenuBar(0, 0); var menu_1 = new Menu ("Menu 1" ); var menu_2 = new Menu ("Menu 2" ); var menu_act = new MenuAction ("Do!", "do.html"); var mi_1_one = new MenuAction ("Menu 1, one", "1_one.html" ); var mi_1_two = new MenuAction ("Menu 1, two", "1_two.html" ); var mn_1_three = new Menu ("Menu 1, three" ); var mi_1_four = new MenuAction ("Menu 1, four", "1_four.html" ); var mi_1_five = new MenuAction ("Menu 1, five", "1_five.html" ); var mi_2_one = new MenuAction ("Menu 2, one", "2_one.html" ); var mi_2_two = new MenuAction ("Menu 2, two", "2_two.html" ); var mi_2_three = new MenuAction ("Menu 2, three", "2_three.html"); var mi_1_three_apple = new MenuAction ("Apple", "Apple" ); var mn_1_three_banana = new Menu ("Banana" ); var mi_1_three_carrot = new MenuAction ("Carrot", "Carrot" ); var mi_banana_green = new MenuAction ("Green", "green.html" ); var mi_banana_yellow = new MenuAction ("Yellow", "yellow.html" ); mn_1_three_banana.add(mi_banana_green); mn_1_three_banana.add(mi_banana_yellow); menu_2.add(mi_2_one ); menu_2.add(mi_2_two ); menu_2.add(mi_2_three); mn_1_three.add(mi_1_three_apple); mn_1_three.add(mn_1_three_banana); mn_1_three.add(mi_1_three_carrot); menu_1.add(mi_1_one ); menu_1.add(mi_1_two ); menu_1.add(mn_1_three); menu_1.add(mi_1_four ); menu_1.add(mi_1_five ); menu_bar.add(menu_1 ); menu_bar.add(menu_2 ); menu_bar.add(menu_act ); document.write(menu_bar); </script> <body onLoad='javascript:basic_menu_load()'> </body> </html> Links |